from bottle import route, run, request, response, view, static_file, post, default_app, redirect
from beaker.middleware import SessionMiddleware
import docker
import redis
from time import sleep
import hashlib
import sys

if len(sys.argv) > 1:
	ip = sys.argv[1]
else:
	ip = '127.0.0.1'

session_opts = {
        'session.type':'file',
        'session.cookei_expires':300,
        'session.data_dir':'./sessions',
        'sessioni.auto':True
        }

dockerClient=docker.Client(base_url='unix://var/run/docker.sock', version='1.22')

exTime=60*60*2

def connRedis(host='127.0.0.1', createDocker=True):
	if createDocker:
		host='127.0.0.1'
		redisContainer=dockerClient.create_container( \
			image='redis:latest', \
			ports=[6379], \
			host_config=dockerClient.create_host_config( \
				port_bindings={6379: (host,6379)} \
			) \
		)
		dockerClient.start(redisContainer.get('Id'))
		sleep(5)
	return redis.Redis(host=host,port=6379)

redisCli=connRedis()

def getLoginInfo():
	s=request.environ.get('beaker.session')
	if 'uid' in s and s['uid'] != '':
		name = redisCli.get('login.'+s['uid'])
		if name != None:
			return {'uid':s['uid'],'name': name}
		else:
			return {}
	else:
		return {}

def encodePassword(passwd):
	return hashlib.sha256(passwd).hexdigest()

def authentication_from_redis(user, passwd):
	print "authentication(redis):",user
	if user is not None and user != '':
		if encodePassword(passwd) != redisCli.get('regist.'+user):
			print "authentication error:",user
			return None
		else:
			return user

def authentication_user(func):
	def wrapper(*args, **kargs):
		loginInfo=getLoginInfo()
		if len(loginInfo) == 0:
			redirect('/')
			return
		return func(**kargs)
	return wrapper

@route('/static/<filepath:path>')
def server_static(filepath):
	return static_file(filepath, root='./static')

def getContainer():
	uid=getLoginInfo().get('uid')
	if uid==None or uid=="":
		return ""

	containerId=redisCli.get('container.'+uid)
	if containerId==None or containerId=="":
		return ""

	container=dockerClient.containers( \
		filters={ \
			"id" : containerId, \
			"ancestor" : "mysql:latest" \
		}, \
		all='true' \
	)
	if container==None or len(container)==0:
		return ""

	return container[0]

@route('/')
@view('index')
def index():
	loginInfo=getLoginInfo()
	container=getContainer()
	return dict(container=container,loginInfo=loginInfo)

@post('/login')
def login():
	user = request.forms.get('user')
	password = request.forms.get('password')
	name=authentication_from_redis(user, password)
	if name!=None:
		print "user "+name+" logon."
		redisCli.set('login.'+user, name)
		redisCli.expire(user,time=exTime)
		s=request.environ.get('beaker.session')
		s['uid']=user
		s.save()
		redirect('/')
		return
	else:
		response.status=401
		return "login failed"

@post('/register')
def register():
	user = request.forms.get('user')
	password = request.forms.get('password')
	password2 = request.forms.get('password2')
	if redisCli.exists('regist.'+user):
		redirect('/')
		return
	if password != password2:
		redirect('/')
		return
	redisCli.set('regist.'+user, encodePassword(password))
	return login()

@route('/containers/create')
@authentication_user
def createDocker():
	uid=getLoginInfo().get('uid')
	if not redisCli.exists('container.'+uid):
		redisCli.set('container.'+uid, "")
		container=dockerClient.create_container( \
			image="mysql:latest", \
			environment={"MYSQL_ROOT_PASSWORD":"admin"}, \
			ports=[3306], \
			host_config=dockerClient.create_host_config( \
				mem_limit="200m", \
				port_bindings={3306: (ip,)} \
			) \
		)
		dockerClient.start(container.get('Id'))
		redisCli.set('container.'+uid, container.get('Id'))
	redirect('/')

@route('/containers/start')
@authentication_user
def startDocker():
	container=getContainer()
	if container != "":
		result = dockerClient.start(container.get('Id'))
		return dockerClient.start(container.get('Id'))
	else:
		response.delete_cookie("containerId")
		return "start failed"

@route('/containers/stop')
@authentication_user
def stopDocker():
	container=getContainer()
	if container != "":
		return dockerClient.stop(container.get('Id'))
	else:
		response.delete_cookie("containerId")
		return "stop failed"

@route('/containers/unpause')
@authentication_user
def unpauseDocker():
	container=getContainer()
	if container != "":
		return dockerClient.unpause(container.get('Id'))
	else:
		response.delete_cookie("containerId")
		return "unpause failed"


app = SessionMiddleware(default_app(), session_opts)
run(app=app, host=ip, port=8080, debug=True)

